package org.walklink.core.config;

import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.walklink.common.exception.ConfigNotFoundException;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 * 配置初始化类
 *
 * @author lidishan
 */
public class ConfigInitializer {

    private static final Logger LOGGER = LogManager.getLogger(ConfigInitializer.class);

    /** 默认配置路径 */
    private static final String DEFAULT_CONFIG_FILE_NAME = "/config/agent.config";
    /** 从DEFAULT_CONFIG_FILE_NAME加载到的配置文件 */
    private static final Properties CONFIG_PROPERTIES = ConfigHelper.getInstance();

    /**
     * 初始化配置
     *
     * @param agentArgs javaagent代理传入的参数
     */
    public static void initConfig(String agentArgs) {
        // 1. 解析agentArgs参数
        Map<String, String> agentArgsMap = parseAgentArgs(agentArgs);

        // 2. 从配置文件中解析参数
        String initFileUrl = agentArgsMap.get(Config.INIT_FILE_URL);
        try (final InputStreamReader configFileStream = loadConfig(initFileUrl)) {
            CONFIG_PROPERTIES.load(configFileStream);
            LOGGER.info("Config init success 配置加载完成, agentArgs = {}", agentArgs);
        } catch (Exception e) {
            LOGGER.error("Config init fail, agentArgs = {}", agentArgs, e);
            throw new ConfigNotFoundException("Config init fail exception=", e);
        }

        // 3. 优先采用服务器传过来的参数信息，将传过来的参数覆盖文件里面的参数信息
        for (Map.Entry<String, String> param : agentArgsMap.entrySet()) {
            CONFIG_PROPERTIES.setProperty(param.getKey(), param.getValue());
        }
    }

    /**
     * 解析agentArgs参数
     * @param agentArgs 代理参数
     * @return 解析的参数集合
     */
    private static Map<String, String> parseAgentArgs(String agentArgs) {
        Map<String, String> agentArgsMap = new HashMap<>(16);
        if (StringUtils.isBlank(agentArgs)) {
            return agentArgsMap;
        }
        String[] params = agentArgs.split("&");
        for (String param : params) {
            if (StringUtils.isBlank(param)) {
                LOGGER.info("Config agentArgs item blank");
                continue;
            }
            String trim = param.toLowerCase(Locale.ROOT).trim();
            String[] item = trim.split("=");
            if (item.length == 0) {
                LOGGER.info("Config agentArgs item length zero item={}", param);
                continue;
            }
            // 将最后格式分割： pinpoint.agentId=192.168.152.15
            // -- => [0]：init.file.url， [1]：192.168.152.15
            String key = item[0].trim();
            String value = item.length > 1 ? item[1] : null;
            agentArgsMap.put(key, value);
        }
        return agentArgsMap;
    }


    /**
     * 加载文件中的配置信息
     * @param initFileUrl 初始化文件地址
     */
    private static InputStreamReader loadConfig(String initFileUrl) throws Exception {
        // 判断是否需要采用新的初始化文件地址
        String fileUrl = StringUtils.defaultIfBlank(initFileUrl, DEFAULT_CONFIG_FILE_NAME);
        // 获取默认配置路径
        File configFile = new File(fileUrl);
        if (configFile.exists() && configFile.isFile()) {
            try {
                LOGGER.info("Config file found in {}.", configFile);
                return new InputStreamReader(new FileInputStream(configFile), StandardCharsets.UTF_8);
            } catch (FileNotFoundException e) {
                throw new ConfigNotFoundException("Failed to load agent.config", e);
            }
        }
        throw new ConfigNotFoundException("Failed to load agent.config.");
    }
}
